#include "sudoku.h"
#include "evaluationFns.h"

//--------------------------------------------------------------------------------------
int reEvaluate(int **grid, int *rowScores, int *colScores, int grLen, int r1, int r2, 
			   int c1, int c2, int &r1Sc, int &r2Sc, int &c1Sc, int &c2Sc, int first)
{
	//EVAKUATES A SOLUTION BY ONLY EXAMINING THE CHANGES MADE BY THE NEIGHBOURHOOD OPERATOR
	//THUS, THIS IS A DELTA-EVALUATION FUNCTION.

	//Save the old scores in case we have to undo the move
	r1Sc=rowScores[r1];
	r2Sc=rowScores[r2];
	c1Sc=colScores[c1];
	c2Sc=colScores[c2];
	
	int i,count,r,c;
	int *nums = new int [grLen+1];
	if (first==0) for(i=0;i<grLen;i++)nums[i]=i;
	else for(i=1;i<grLen+1;i++)nums[i]=i;

	//Go through the first row and reevaluate
	count = 0;
	for(c=0;c<grLen;c++){
		nums[grid[r1][c]]=-1;
	}
	if (first==0){
		for(i=0;i<grLen;i++){
			if(nums[i]!=-1)count++;
		}
	}
	else{
		for(i=1;i<grLen+1;i++){
			if(nums[i]!=-1)count++;
		}
	}
	rowScores[r1]=count;
	//if there was another row involved, reevaluate that too
	if(r1!=r2){
		if (first==0) for(i=0;i<grLen;i++)nums[i]=i;
		else for(i=1;i<grLen+1;i++)nums[i]=i;
		count = 0;
		for(c=0;c<grLen;c++){
			nums[grid[r2][c]]=-1;
		}
		if (first==0){
			for(i=0;i<grLen;i++){
				if(nums[i]!=-1)count++;
			}
		}
		else{
			for(i=1;i<grLen+1;i++){
				if(nums[i]!=-1)count++;
			}
		}
		rowScores[r2]=count;
	}
	
	//Do the same for the columns
	if (first==0) for(i=0;i<grLen;i++)nums[i]=i;
	else for(i=1;i<grLen+1;i++)nums[i]=i;
	count = 0;
	for(r=0;r<grLen;r++){
		nums[grid[r][c1]]=-1;
	}
	if (first==0){
		for(i=0;i<grLen;i++){
			if(nums[i]!=-1)count++;
		}
	}
	else{
		for(i=1;i<grLen+1;i++){
			if(nums[i]!=-1)count++;
		}
	}
	colScores[c1]=count;
	//if there was another column involved, reevaluate it
	if(c1!=c2){
		if (first==0) for(i=0;i<grLen;i++)nums[i]=i;
		else for(i=1;i<grLen+1;i++)nums[i]=i;
		count = 0;
		for(r=0;r<grLen;r++){
			nums[grid[r][c2]]=-1;
		}
		if (first==0){
			for(i=0;i<grLen;i++){
				if(nums[i]!=-1)count++;
			}
		}
		else{
			for(i=1;i<grLen+1;i++){
				if(nums[i]!=-1)count++;
			}
		}
		colScores[c2]=count;
	}
	
	//Add up the arrays
	int colTotal=0, rowTotal=0;
	for(i=0;i<grLen;i++){
		rowTotal=rowTotal+rowScores[i];
		colTotal=colTotal+colScores[i];
	}

	delete [] nums;
	return(colTotal+rowTotal);	
}

//--------------------------------------------------------------------------------------
int evaluate(int **grid, int sqLen, int grLen, int *rowScores, int *colScores, int first)
{
	//TAKES AN ENTIRE SOLUTION AND EVALUATES IT	
	int i,count,r,c;
	int *nums = new int [grLen+1];
	if (first==0) for(i=0;i<grLen;i++)nums[i]=i;
	else for(i=1;i<grLen+1;i++)nums[i]=i;

	//Go through each row and determine the score
	for(r=0;r<grLen;r++){
		count = 0;
		for(c=0;c<grLen;c++){
			nums[grid[r][c]]=-1;
		}
		//count the number of nums not present in the row
		if (first==0){
			for(i=0;i<grLen;i++){
				if(nums[i]!=-1)count++;
			}
		}
		else{
			for(i=1;i<grLen+1;i++){
				if(nums[i]!=-1)count++;
			}
		}
		rowScores[r]=count;
		//cout<<"\nRow "<<r<<" has "<<count<<" numbers missing";
		//Reset nums Array
		if (first==0) for(i=0;i<grLen;i++)nums[i]=i;
		else for(i=1;i<grLen+1;i++)nums[i]=i;
	}

	//Go through each col and determine the score
	for(c=0;c<grLen;c++){
		count = 0;
		for(r=0;r<grLen;r++){
			nums[grid[r][c]]=-1;
		}
		//count the number of nums not present in the row
		if(first==0){
			for(i=0;i<grLen;i++){
				if(nums[i]!=-1)count++;
			}
		}
		else{
			for(i=1;i<grLen+1;i++){
				if(nums[i]!=-1)count++;
			}
		}
		colScores[c]=count;
		//cout<<"\nCol "<<c<<" has "<<count<<" numbers missing";
		//Reset nums Array
		if (first==0) for(i=0;i<grLen;i++)nums[i]=i;
		else for(i=1;i<grLen+1;i++)nums[i]=i;
	}
	
	//Add up the arrays
	int colTotal=0, rowTotal=0;
	for(i=0;i<grLen;i++){
		rowTotal=rowTotal+rowScores[i];
		colTotal=colTotal+colScores[i];
	}
	delete [] nums;
	return(colTotal+rowTotal);	
}

//--------------------------------------------------------------------------------------
void doMove(int **grid, bool **fixed, int grLen, int sqLen, int &r1, int &r2, int &c1, int &c2
#ifdef USE_HEURISTIC_SELECTION_LIBRARY
    , MoveSelector& mhs
#endif
)
{
#ifndef USE_HEURISTIC_SELECTION_LIBRARY
	//pick first cell to swap
	do{
		r1=rand()%grLen;
		c1=rand()%grLen;
	}while(fixed[r1][c1]);
	//pick second cell to swap (must be not fixed AND must be in the same
	//square as the first cell
	do{
		r2=(rand()%sqLen)+((r1/sqLen)*sqLen);
		c2=(rand()%sqLen)+((c1/sqLen)*sqLen);
	}while(fixed[r2][c2] || (r1==r2 && c1==c2) );
#else
        RCRC rcrc = mhs.select();
        r1 = rcrc.r1;
        c1 = rcrc.c1;
        r2 = rcrc.r2;
        c2 = rcrc.c2;
#endif
	
	//swap the two cells
	int temp;
	temp=grid[r1][c1];
	grid[r1][c1]=grid[r2][c2];
	grid[r2][c2]=temp;
}

//--------------------------------------------------------------------------------------
void undoMove(int **grid, int *rowScores, int *colScores, int grLen, int r1, int r2,
			  int c1, int c2, int r1Sc, int r2Sc, int c1Sc, int c2Sc)
{
	//this procedure should do things (1)swap the elements back, and (2) reset the
	//rowScores and colScores Array
	int temp;
	temp=grid[r1][c1];
	grid[r1][c1]=grid[r2][c2];
	grid[r2][c2]=temp;

	rowScores[r1]=r1Sc;
	rowScores[r2]=r2Sc;
	colScores[c1]=c1Sc;
	colScores[c2]=c2Sc;
}

